#include <iostream>
#include <queue>
#include <pthread.h>

#define max_q 5

template <class T>
class Blockqueue
{
public:
    Blockqueue()
    :_max(max_q)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_pcond, nullptr);
        pthread_cond_init(&_ccond, nullptr);
    }
    //生产数据
    void bqpush(T val)
    {
        pthread_mutex_lock(&_mutex);
        while(is_full())
        {
            pthread_cond_wait(&_pcond, &_mutex);
        }

        _bq.push(val);
        pthread_cond_signal(&_ccond);
        pthread_mutex_unlock(&_mutex);
    }
    //消费数据
    T bqpop()
    {
        pthread_mutex_lock(&_mutex);
        while(is_empty())
        {
            pthread_cond_wait(&_ccond, &_mutex);
        }

        T tmp = _bq.front();
        _bq.pop();
        pthread_cond_signal(&_pcond);
        pthread_mutex_unlock(&_mutex);
        return tmp;
    }

    ~Blockqueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_pcond);
        pthread_cond_destroy(&_ccond);
    }
private:
    bool is_empty()
    {
        return _bq.empty();
    }
    bool is_full()
    {
        return _bq.size() == _max ? true : false;
    }
private:
    std::queue<T> _bq; //阻塞队列
    int _max; //最大存储量
    pthread_mutex_t _mutex; //互斥锁
    pthread_cond_t _pcond; //生产者条件变量
    pthread_cond_t _ccond; //消费者条件变量
};

